package com.natasa.monitor.service;

import java.util.List;

import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedOperationParameter;
import org.springframework.jmx.export.annotation.ManagedOperationParameters;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
import org.springframework.util.CollectionUtils;

import com.natasa.monitor.dao.ITaskRuleDAO;
import com.natasa.monitor.entity.task.TaskRule;


/**
 * 定时任务管理类,该类从数据库中获取定时任务的执行规则。 并且该类会被包装成Mbean，对外提供刷新方法，方便对于任务的执行情况进行管理
 * 
 * @author jianfeihit
 * 
 */
@ManagedResource
public class TaskManager {
    protected Logger    logger         = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private Scheduler   scheduler      = null;
    
    @Autowired
    private TaskFactory taskFactory = null;

    @Autowired
    private ITaskRuleDAO     taskDAO        = null;

    /**
     * 从数据库中取出新修改或新添加的定时任务规则,该方法暴漏成MBean的方法
     * 
     * @return
     */
    @ManagedOperation
    public void refreshTaskRuleList() {
        List<TaskRule> taskRuleList = taskDAO.getTaskRule();
        
        if(CollectionUtils.isEmpty(taskRuleList)){
        	logger.info("没有获取到需要执行的任务规则");
        	return;
        }
        
        for (TaskRule taskRule : taskRuleList) {
            createJob(taskRule);
        }
    }

    /**
     * 具体创建任务的类
     * 
     * @param taskRule
     */
    private void createJob(TaskRule taskRule) {
        try {
            String name = taskRule.getTaskId();
            String groupName = "" + taskRule.getTaskType();

            // 删除原来的定时任务
            JobDetail JobDetail = scheduler.getJobDetail(name, groupName);
            if (JobDetail != null) {
                scheduler.deleteJob(name, groupName);
            }

            // 准备定时任务的数据
            AbstractMonitorTask taskHandler = (AbstractMonitorTask) taskFactory.getTaskHandler(taskRule.getTaskHandler());
            if (taskHandler == null) {
                logger.error("task的处理类配置错误。taskId=" + taskRule.getTaskId() + ",taskProcessBean=" + taskRule.getTaskHandler());
                return;
            }
            taskHandler.setMonitorRuleId(taskRule.getMonitorRuleId());
            
            // 设置定时任务
            MethodInvokingJobDetailFactoryBean jobDetailFactory = new MethodInvokingJobDetailFactoryBean();
            jobDetailFactory.setTargetObject(taskHandler);
            jobDetailFactory.setTargetMethod("doTask");
            jobDetailFactory.setGroup(groupName);
            jobDetailFactory.setName(name);
            jobDetailFactory.afterPropertiesSet();
            JobDetail jobDetail = (JobDetail) jobDetailFactory.getObject();
            CronTrigger trigger = new CronTrigger(taskRule.getTaskId(), taskRule.getTaskType(), taskRule.getConExpress());
            scheduler.scheduleJob(jobDetail, trigger);
            logger.info("添加任务成功。任务规则编号=" + taskRule.getTaskId() + "|#任务执行规则=" + taskRule.getConExpress());

            if (!scheduler.isStarted()) {
                scheduler.start();
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("创建定时任务时发生异常,e=", e);
        }
    }
    
    /**
     * 手动执行的方法
     * @param taskId
     */
    @ManagedOperation
    @ManagedOperationParameters({  
        @ManagedOperationParameter(name = "taskId",description="需要执行的任务编号")})
    public void executeTask(String taskId){
    	TaskRule taskRule = taskDAO.getTaskRuleById(taskId);
        
    	// 准备定时任务的数据
    	AbstractMonitorTask taskHandler = (AbstractMonitorTask) taskFactory.getTaskHandler(taskRule.getTaskHandler());
        if (taskHandler == null) {
            logger.error("task的处理类配置错误。taskId=" + taskRule.getTaskId() + ",taskProcessBean=" + taskRule.getTaskHandler());
            return;
        }
        taskHandler.setMonitorRuleId(taskRule.getMonitorRuleId());
        taskHandler.doTask();
    }
}
